// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CLOUDAPPENGINE_CAEENGINCONTROL_H
#define CLOUDAPPENGINE_CAEENGINCONTROL_H

#include <cstdio>
#include <cstdint>
#include "../cae_common/CaeLogConfig.h"
#include "../cae_CPHMediaEngine/CPHMediaEngine.h"
#include "../cae_dataPipe/CaeInput.h"
#include "../cae_dataPipe/CaeMsgHead.h"

enum Result {
    SUCCESS = 0,
    FAILED = -1,
    H265_NOT_SUPPORT = -2,
    ERR_TOUCH_PARAMS_TOUCH_FAULT = -1000,
    ERR_TOUCH_PARAMS_KEY_FAULT = -1001,
    ERR_TOUCH_INJECT_TOUCH_FAILED = -1100,
    ERR_TOUCH_INJECT_KEY_FAILED = -1101,
    ERR_AUDIO_PARAMS_FAULT = -2000,
    ERR_AUDIO_OPEN_FAILED = -2100,
    ERR_AUDIO_CLOSE_FAILED = -2200,
    ERR_VIDEO_PARAMS_FAULT = -3000,
    ERR_VIDEO_OPEN_FAILED = -3100,
    ERR_VIDEO_CLOSE_FAILED = -3200,
    ERR_VIDEO_POOL_ELB_FAULT = -3300,
    ERR_VIDEO_POOL_ELB_ILLEGAL = -3301,
    ERR_VIDEO_POOL_PARAMS_FAULT = -3302,
    ERR_VIDEO_POOL_ELB_NULL = 3303,
    ERR_SCREENSHOT_OPEN_REPEAT = -3152
};

class CaeEngineControl {
public:
    CaeEngineControl();

    ~CaeEngineControl();

    static CaeEngineControl &GetInstance();
    CaeEngineControl(const CaeEngineControl &) = delete;
    CaeEngineControl &operator = (const CaeEngineControl &) = delete;

    int Init();

    Result OpenMediaStream();

    Result CloseMediaStream();

    Result OpenAudio() const;

    Result CloseAudio();

    void OpenVirtualDevices(std::string sdkVersion);

    void CloseVirtualDevices();

    Result SetMediaConfig() const;

    Result RequestIframe();

    bool IsSupportH265() const;

    Result SetPhysicalResolution();

    Result OpenScreenShots(uint32_t jpegWidth, uint32_t jpegHeight);

    Result CloseScreenshot();

    Result VmiDeviceSend(VmiDeviceType deviceType, uint8_t* data, uint32_t len) const;

    void HandleLocationMsg(uint8_t *virtualDeviceData, uint32_t virtualDeviceDataSize) const;

    int HandleTouchMsg(CaeTouchEventMsg *caeTouchEventMsg) const;

    int HandleKeyMsg(CaeKeyEventMsg *caeKeyEventMsg) const;

    int HandleMotionMsg(void* buf, uint64_t length) const;

    uint32_t GetCaptureLatency() const;

    uint32_t GetEncodeLatency() const;
    
    CPHMediaEngine *m_cphMediaEngine;

    volatile uint8_t m_orientation;
    volatile bool m_changeOrientation;

    static uint32_t m_pktIndex;
    volatile uint32_t m_width;
    volatile uint32_t m_height;
    std::mutex m_initLock;

    volatile uint64_t m_startCaptureTimestamp;
    volatile uint64_t m_endCaptureTimestamp;
    volatile uint64_t m_startEncodeTimestamp;
    volatile uint64_t m_endEncodeTimestamp;

    const char* GetMediaFeatures() const;

private:
    Result InitVmiDevice(VmiDeviceType deviceType, VmiConfigParams& params) const;

    Result EnableVmiDevice(VmiDeviceType deviceType) const;

    Result DisableVmiDevice(VmiDeviceType deviceType) const;

    Result DestroyVmiDevice(VmiDeviceType deviceType) const;

    uint8_t GetVmiDeviceStatus(VmiDeviceType deviceType) const;

    bool m_isMediaStreamOpening = false;
    bool m_isVirtualDeviceOpening = false;
    bool m_isScreenShotOpening = false;
    volatile uint32_t m_screenShotWidth;
    volatile uint32_t m_screenShotHeight;
};
#endif // CLOUDAPPENGINE_CAEENGINCONTROL_H
